from rest_framework import serializers
from rest_framework_jwt.serializers import jwt_payload_handler, jwt_encode_handler
from django.core.cache import cache
from django.conf import settings

from . import models
import re


# 多方式登录
class LoginModelSerializer(serializers.ModelSerializer):
    username = serializers.CharField(write_only=True)
    password = serializers.CharField(write_only=True)

    class Meta:
        model = models.User
        fields = ('username', 'password')

    def validate(self, attrs):
        user = self._many_method_login(**attrs)

        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        self.user = user
        self.token = token

        return attrs

    def _many_method_login(self, **attrs):
        username = attrs.get('username')
        password = attrs.get('password')

        if re.match(r'.*@.*', username):
            user = models.User.objects.filter(email=username).first()
        elif re.match(r'^1[3-9][0-9]{9}$', username):
            user = models.User.objects.filter(mobile=username).first()
        else:
            user = models.User.objects.filter(username=username).first()

        if not user:
            raise serializers.ValidationError({'username': '账号有误'})
        if not user.check_password(password):
            raise serializers.ValidationError({'password': '密码有误'})

        return user


# 手机验证码登录
class LoginMobileModelSerializer(serializers.ModelSerializer):
    mobile = serializers.CharField(write_only=True, min_length=11, max_length=11)
    code = serializers.CharField(write_only=True, min_length=4, max_length=4)

    class Meta:
        model = models.User
        fields = ('mobile', 'code')

    def validate_mobile(self, value):
        if re.match(r'^1[3-9][0-9]{9}$', value):
            return value
        raise serializers.ValidationError({'mobile': '手机号格式有误'})

    def validate_code(self, value):
        try:
            int(value)
            return value
        except:
            raise serializers.ValidationError({'code': '验证码格式有误'})

    def validate(self, attrs):
        user = self._get_user(**attrs)

        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        self.user = user
        self.token = token

        return attrs

    def _get_user(self, **attrs):

        mobile = attrs.get('mobile')

        code = attrs.get('code')
        user = models.User.objects.filter(mobile=mobile).first()

        if not user:
            raise serializers.ValidationError({'mobile': '该手机未注册'})

        old_code = cache.get(settings.SMS_CACHE_KEY % mobile)
        if code != old_code:
            raise serializers.ValidationError({'code': '验证码有误'})

        # cache.set(settings.SMS_CACHE_KEY % mobile, '0000', 0)
        return user


# 手机验证码注册
class RegisterMobileSerializer(serializers.ModelSerializer):
    code = serializers.CharField(write_only=True, min_length=4, max_length=4)

    class Meta:
        model = models.User
        fields = ('mobile', 'password', 'code')
        extra_kwargs = {
            'mobile': {
                'min_length': 11,
                'max_length': 11,
            },
            'password': {
                'min_length': 6,
                'max_length': 18,
            }
        }

    def validate_mobile(self, value):
        if re.match(r'^1[3-9][0-9]{9}$', value):
            return value
        raise serializers.ValidationError({'mobile': '手机号格式有误'})

    def validate_code(self, value):
        try:
            int(value)
            return value
        except:
            raise serializers.ValidationError({'code': '验证码格式有误'})

    def validate_password(self, value):
        return value

    def validate(self, attrs):
        mobile = attrs.get('mobile')
        code = attrs.pop('code')
        old_code = cache.get(settings.SMS_CACHE_KEY % mobile)
        if code != old_code:
            raise serializers.ValidationError({'code': '验证码有误'})
        # cache.set(settings.SMS_CACHE_KEY % mobile, '0000', 0)

        attrs['username'] = mobile
        attrs['email'] = '%s@oldboy.com' % mobile

        return attrs

    def create(self, validated_data):
        return models.User.objects.create_user(**validated_data)
